package com.forum.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.img.ImgUtil;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@RestController
@RequestMapping("/api/upload")
@Slf4j
public class FileUploadController {

    @Value("${forum.upload.path}")
    private String uploadPath;

    @Value("${forum.upload.url-prefix}")
    private String uploadUrlPrefix;

    // 允许的文件类型
    private static final List<String> ALLOWED_MIME_TYPES = List.of(
        "image/jpeg", "image/png", "image/gif", "image/webp"
    );

    // 最大文件大小 5MB
    private static final long MAX_FILE_SIZE = 5 * 1024 * 1024;

    // 最大图片宽度和高度
    private static final int MAX_IMAGE_WIDTH = 1920;
    private static final int MAX_IMAGE_HEIGHT = 1080;

    @PostMapping("/image")
    public ResponseEntity<?> uploadImages(@RequestParam("files") MultipartFile[] files) {
        List<String> uploadedUrls = new ArrayList<>();

        for (MultipartFile file : files) {
            try {
                // 文件验证
                validateFile(file);

                // 压缩和处理图片
                BufferedImage processedImage = processImage(file);

                // 生成唯一文件名
                String originalFilename = file.getOriginalFilename();
                String suffix = FileUtil.getSuffix(originalFilename);
                String datePath = DateUtil.format(DateUtil.date(), "yyyy/MM/dd");
                String filename = IdUtil.simpleUUID() + "." + suffix;
                
                // 创建目标文件路径
                File targetDir = new File(uploadPath + "/images/" + datePath);
                if (!targetDir.exists()) {
                    targetDir.mkdirs();
                }

                File dest = new File(targetDir, filename);

                // 保存处理后的图片
                ImgUtil.write(processedImage, dest);
                
                // 构建可访问的URL
                String relativePath = "/images/" + datePath + "/" + filename;
                String fullUrl = uploadUrlPrefix + relativePath;
                
                uploadedUrls.add(fullUrl);
                log.info("文件上传成功: {}", fullUrl);
            } catch (Exception e) {
                log.error("文件上传失败", e);
                return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body("文件上传失败: " + e.getMessage());
            }
        }

        return ResponseEntity.ok(uploadedUrls);
    }

    // 文件验证
    private void validateFile(MultipartFile file) throws Exception {
        if (file.isEmpty()) {
            throw new IllegalArgumentException("上传文件不能为空");
        }

        // 检查文件大小
        if (file.getSize() > MAX_FILE_SIZE) {
            throw new IllegalArgumentException("文件大小不能超过5MB");
        }

        // 检查文件类型
        String contentType = file.getContentType();
        if (contentType == null || !ALLOWED_MIME_TYPES.contains(contentType)) {
            throw new IllegalArgumentException("不支持的文件类型");
        }
    }

    // 图片处理和压缩
    private BufferedImage processImage(MultipartFile file) throws IOException {
        BufferedImage originalImage = ImageIO.read(file.getInputStream());

        // 检查图片尺寸
        int width = originalImage.getWidth();
        int height = originalImage.getHeight();

        // 如果图片超过最大尺寸，则压缩
        if (width > MAX_IMAGE_WIDTH || height > MAX_IMAGE_HEIGHT) {
            // 使用 Thumbnailator 压缩图片
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            Thumbnails.of(originalImage)
                .size(MAX_IMAGE_WIDTH, MAX_IMAGE_HEIGHT)
                .outputQuality(0.8)
                .toOutputStream(outputStream);

            ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
            return ImageIO.read(inputStream);
        }

        return originalImage;
    }
}
